#pragma once
#include <iostream>
#include <unistd.h>
#include <pthread.h>
#include <vector>
#include "Sem.hpp"
#include "Mutex.hpp"

namespace RingQueueModule
{
    using namespace MySemModule;
    using namespace MpthreayMutex;

    template<class T>
    class ringqueue
    {
    public:
        ringqueue(int cap) :_cap(cap), 
            spacesem(cap),
            datasem(0),
            c_step(0),
            p_step(0),
            _rq(cap)
        {
        }
        void Equeue(T& in) //生产者
        {
            spacesem.P(); //生产者申请一份空间
            {
                LockGround lock(_p_lock); //为什么要放在申请信号量之后呢?
                //让多线程并行申请信号量，提高效率，信号量被设计为原子性
                //以买电影票为例，先加锁 : 先排队在买票
                //先申请信号量 : 先买票，买了票的直接进去就行，没买着的就等着。
                _rq[p_step] = in;
                p_step++;
                p_step %= _cap;
            }
            datasem.V(); //生产者没消耗一份空间就会多出一份数据

        }
        void Pop(T* out)
        {
            datasem.P(); //消费者申请一份数据
            {
                LockGround lock(_c_lock);
                *out = _rq[c_step];
                c_step++;
                c_step %= _cap;
            }
            spacesem.V(); 

        }
        ~ringqueue()
        {

        }
    private:
        std::vector<T> _rq;
        int _cap;
        Sem spacesem; //空间信号量 
        Sem datasem;  //数据信号量 
        int c_step;
        int p_step;
        Mutex _p_lock;
        Mutex _c_lock;
    };
}

